SPB Git forge

spb/hilmacorp

Public
1commits 1branches 0releases
29.2 MBsize
maindefault branch
20 days agolast push
TypeScript 93.3% JavaScript 4.4% CSS 2.3%
2.6 KB · 85 lines tsx
Raw Blame History
1/**2 * Author: Simon-Pierre Boucher3 * Contact: contact@spboucher.ai4 * Project: Hilmacorp.ai — Web Platform5 * File: app/[locale]/layout.tsx6 * Description: Locale-scoped root layout — HTML shell, fonts, global metadata, header and footer7 */89import type { Metadata } from "next";10import { Inter, Fraunces } from "next/font/google";11import { notFound } from "next/navigation";12import Header from "@/components/Header";13import Footer from "@/components/Footer";14import CookieConsent from "@/components/CookieConsent";15import { getMessages, isLocale, locales, type Locale } from "@/lib/i18n";16import "@/app/globals.css";1718const inter = Inter({ subsets: ["latin"], variable: "--font-inter", display: "swap" });19const fraunces = Fraunces({ subsets: ["latin"], variable: "--font-fraunces", display: "swap" });2021const SITE_URL = process.env.NEXT_PUBLIC_SITE_URL ?? "https://www.hilmacorp.ai";2223export function generateStaticParams() {24  return locales.map((locale) => ({ locale }));25}2627export async function generateMetadata({28  params,29}: {30  params: Promise<{ locale: string }>;31}): Promise<Metadata> {32  const { locale } = await params;33  if (!isLocale(locale)) return {};34  const messages = getMessages(locale);35  return {36    metadataBase: new URL(SITE_URL),37    title: {38      default: messages.meta.home.title,39      template: `%s — ${messages.meta.siteName}`,40    },41    description: messages.meta.home.description,42    alternates: {43      languages: { fr: "/fr", en: "/en" },44    },45    openGraph: {46      type: "website",47      siteName: messages.meta.siteName,48      locale: locale === "fr" ? "fr_CA" : "en_US",49      url: `${SITE_URL}/${locale}`,50      title: messages.meta.home.title,51      description: messages.meta.home.description,52    },53    twitter: {54      card: "summary",55      title: messages.meta.home.title,56      description: messages.meta.home.description,57    },58    robots: { index: true, follow: true },59  };60}6162export default async function LocaleLayout({63  children,64  params,65}: {66  children: React.ReactNode;67  params: Promise<{ locale: string }>;68}) {69  const { locale } = await params;70  if (!isLocale(locale)) notFound();71  const typedLocale = locale as Locale;72  const messages = getMessages(typedLocale);7374  return (75    <html lang={typedLocale} className={`${inter.variable} ${fraunces.variable}`}>76      <body className="flex min-h-screen flex-col font-sans">77        <Header locale={typedLocale} nav={messages.nav} />78        <main className="flex-1">{children}</main>79        <Footer locale={typedLocale} messages={messages} />80        <CookieConsent locale={typedLocale} strings={messages.cookies} />81      </body>82    </html>83  );84}85